package com.DoubleLinkedList;

public class DoubleLinkedList {
    //初始化头结点
    private DHeroNode head = new DHeroNode();

    public DHeroNode getHead() {
        return head;
    }

    //双向链表的遍历和单向链表的遍历方式相同
    public void showLinkedList() {
        //先判断链表是否为空，即head.next = null
        if (head.next == null) {
            System.out.println("当前链表为空，没有结点");
            return;
        }
        //没有退出表示至少存在一个结点
        DHeroNode temp = head.next;
        do {
            System.out.println(temp);
            temp = temp.next;
        } while (temp != null);
    }

    /**
     * 添加结点：直接将结点添加到链表尾部
     */
    public void addNode(DHeroNode heroNode) {
        //头结点head不能动，通过添加辅助变量指向head遍历获取最后一个结点
        DHeroNode temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        //如果不是最后一个结点，就将下一个结点赋给temp
        //当退出循环时，temp就指向了最后一个结点
        //将最后个结点的next指向新的结点，并将新链表的前驱节点指向最后一个节点
        temp.next = heroNode;
        heroNode.pre = temp;
    }

    /**
     * 按照编号大小顺序进行添加
     * @param node
     */
    public void addNodeByOrder(DHeroNode node){
        DHeroNode temp = head;
        boolean flag = false;
        //需要找到插入位置的前一个节点
        while(temp.next != null){
            // 一旦temp为最后一个结点
            // 或不是最后一个结点时，后面结点的编号大于或等于插入结点编号则退出循环，表示temp位置就已找到
            if(temp.next.no > node.no){
                break;
            }
            if(temp.next.no == node.no){
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if(flag){
            System.out.println("节点编号"+node.no+"已存在，无需重复插入相同的数据");
        }else {
            //双向链表在添加节点时一定是先连接后面的节点再连接前面的节点
            //在连接后面的节点时，需要判断是否为最后一个节点，不然temp.next=null会出现空指针异常
            if(temp.next != null){
                node.next = temp.next;
                temp.next.pre = node;
            }
            node.pre = temp;
            temp.next = node;

        }
    }

    /**
     * 修改双向链表中节点的内容。和单向链表中的更新一样
     */
    public void updateNode(DHeroNode node) {
        //判读链表是否为空
        if (head.next == null) {
            System.out.println("该链表为空链表");
            return;
        }
        DHeroNode temp = head.next;
        //通过flag判读节点是否存在
        boolean flag = false;
        while (temp != null) {
            if (temp.no == node.no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            //flag为true,表示已经找到结点
            temp.name = node.name;
            temp.nickName = node.nickName;
        } else {
            System.out.println("结点编号为" + node.no + "不存在，请添加该结点");
        }
    }

    /*
    单链表中删除节点时由于需要将删除节点的前一个节点的next指向删除节点的后一个节点，所以辅助变量找删除节点的前一个节点
    而在双向链表中的节点存在前驱指针，所以可以直接将待删除的节点定义为辅助节点
     */
    public void deleteByNo(int no) {
        if (head.next == null) {
            System.out.println("该链表为空链表");
            return;
        }
        DHeroNode temp = head.next;
        boolean flag = false;
        while (temp != null) {
            if (temp.no == no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.pre.next = temp.next;
            //如果删除节点为最后一个节点时，temp.next.pre会出现空指针问题
            if (temp.next != null) {
                temp.next.pre = temp.pre;
            }
        } else {
            System.out.println("没有找到编号为" + no + "的结点，删除失败");
        }

    }

}
